﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.IO;
using System.Reflection;


namespace HomeworkApp
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private int _numValue = 1;
        public int NumValue
        {
            get { return _numValue; }
            set
            {
                _numValue = value;
                txtNum.Text = value.ToString();
            }
        }

        private void AddTaskBox()
        {
            this.Tasks_List.Children.Add(new TaskBox(String.Format("Задача {0}.", this._numValue), this));
        }

        private void RemoveTaskBox()
        {
            this.Tasks_List.Children.RemoveAt(this.Tasks_List.Children.Count - 1);
        }

        private void cmdUp_Click(object sender, RoutedEventArgs e)
        {
            NumValue++;
            this.AddTaskBox();
        }

        private void cmdDown_Click(object sender, RoutedEventArgs e)
        {
            if (NumValue > 1)
            {
                NumValue--;
                this.RemoveTaskBox();
            }
        }

        private void txtNum_TextChanged(object sender, TextChangedEventArgs e)
        {
            if (!int.TryParse(txtNum.Text, out _numValue))
            {
                txtNum.Text = _numValue.ToString();
            }
        }

        public MainWindow()
        {
            InitializeComponent();
            ResetTasksList();
        }

        private void ResetTasksList()
        {
            this.Tasks_List.Children.Clear();
            txtNum.Text = "1";
            this.AddTaskBox();
        }

        private static void ShowMessage(string message)
        {
            MessageBox.Show(message, "Съобщение", MessageBoxButton.OK, MessageBoxImage.Information);
        }

        private static void ShowError(string message, string caption)
        {
            MessageBox.Show(message, caption, MessageBoxButton.OK, MessageBoxImage.Error);
        }

        private static bool AskForConfirmation(string message)
        {
            MessageBoxResult answer = MessageBox.Show(message, "Потвърдете", MessageBoxButton.YesNo, MessageBoxImage.Question);
            return answer == MessageBoxResult.Yes;
        }

        private bool CheckForDefaultState()
        {
            bool additionalCommentIsEmpty = String.IsNullOrEmpty(this.AdditionalComment_TextBlock.Text);
            bool tasksCondition = this.Tasks_List.Children.Count == 1;
            bool finalTaskCondition = tasksCondition;
            if (tasksCondition)
            {
                TaskBox taskOne = this.Tasks_List.Children[0] as TaskBox;
                bool firstTaskCondition = (taskOne.Status == TaskStatus.Empty) && String.IsNullOrEmpty(taskOne.Comment);
                finalTaskCondition = firstTaskCondition && tasksCondition;
            }
            bool inDefaultState = finalTaskCondition && additionalCommentIsEmpty;
            return inDefaultState;
        }

        private void CloseWindow_Click(object sender, RoutedEventArgs e)
        {
            this.Close();
        }

        private static MessageBoxResult AskForExtendedConfirmation(string message)
        {
            MessageBoxResult confirm = MessageBox.Show(message, "Потвърдете", MessageBoxButton.YesNoCancel, MessageBoxImage.Question);
            return confirm;
        }

        private void GenerateOutput_Click(object sender, RoutedEventArgs e)
        {
            GenerateRecension();

        }

        private void GenerateRecension()
        {
            this.Cursor = Cursors.Wait;
            if (File.Exists(this.patternFile))
            {
                Dictionary<string, string> pattern = ReadPattern();
                if (pattern == null)
                {
                    ShowError("Прочетеният шаблон не отговаря на изискванията, рецензията се генерира стандартно.", "Грешка");
                    GenerateDefaultRecension();
                }
                else
                {
                    GenerateRecensionByPattern(pattern);
                }
            }
            else
            {
                GenerateDefaultRecension();
            }
            this.Cursor = Cursors.Arrow;
        }

        private string patternFile = "pattern.txt";

        private Dictionary<string, string> ReadPattern()
        {
            Dictionary<string, string> result = new Dictionary<string, string>();
            List<string> patternFileLines = new List<string>();
            using (StreamReader reader = new StreamReader(this.patternFile))
            {
                string line = reader.ReadLine();
                StringBuilder dc = new StringBuilder();
                string id = "";
                bool hasMetMarker = false;
                bool isBlockOpened = false;
                while (line != null)
                {
                    patternFileLines.Add(line);
                    if (line == "{")
                    {
                        isBlockOpened = true;
                        hasMetMarker = false;
                        dc.Clear();
                    }
                    else if (line == "}")
                    {
                        if (isBlockOpened)
                        {
                            if (!result.ContainsKey(id))
                            {
                                result.Add(id, dc.ToString());
                            }
                            isBlockOpened = false;
                        }
                    }
                    else if (line.Length > 2 && isBlockOpened && line[0] == '-' && line[1] == '>')
                    {
                        id = line.Substring(2);
                        hasMetMarker = true;
                        dc.AppendLine("@placehere");
                    }
                    else if (!String.IsNullOrEmpty(line) && isBlockOpened)
                    {                        
                        dc.AppendLine(line);
                    }
                    line = reader.ReadLine();
                }
            }
            if (result.Count != 2)
            {
                return null;
            }
            if (!result.ContainsKey("comment on tasks") || !result.ContainsKey("extra comment"))
            {
                return null;
            }
            return result;
        }
        private void GenerateRecensionByPattern(Dictionary<string, string> headerCollection)
        {
            StringBuilder resultBuilder = new StringBuilder();
            StringBuilder tasksResBuilder = new StringBuilder();
            bool hasTasksToWrite = false;
            int k=0;
            foreach (TaskBox task in this.Tasks_List.Children)
            {
                if (task.ShowTaskInReport)
                {
                    string taskName = task.TaskName;
                    TaskStatus taskStatus = task.Status;
                    string taskStatusString = "";
                    switch (taskStatus)
                    {
                        case TaskStatus.Finished:
                            taskStatusString = "Задачата е направена.";
                            break;
                        case TaskStatus.NotFinished:
                            taskStatusString = "Задачата не е довършена.";
                            break;
                        default:
                            taskStatusString = "Задачата e празна.";
                            break;
                    }
                    hasTasksToWrite = true;
                    if (k == this.Tasks_List.Children.Count - 1)
                    {
                        tasksResBuilder.Append(string.Format("{0} {1} {2}", taskName, taskStatusString, task.Comment));
                    }
                    else
                    {
                        tasksResBuilder.AppendLine(string.Format("{0} {1} {2}", taskName, taskStatusString, task.Comment));
                    }
                    k++;
                }
            }
            bool hasExtraComment = String.IsNullOrEmpty(this.AdditionalComment_TextBlock.Text) == false;
            if (hasTasksToWrite == false && hasExtraComment == false)
            {
                ShowMessage("Липсва достатъчно съдържание за генериране на рецензия.");
                return;
            }
            if (hasTasksToWrite)
            {
                string finalComment = headerCollection["comment on tasks"].Replace("@placehere", tasksResBuilder.ToString());
                resultBuilder.Append(finalComment);  
            }
            if (hasExtraComment)
            {
                string finalComment = headerCollection["extra comment"].Replace("@placehere",this.AdditionalComment_TextBlock.Text);
                resultBuilder.Append(finalComment);                
            }
            SaveAndOpenRecension(resultBuilder);
        }

        private static void SaveAndOpenRecension(StringBuilder resultBuilder)
        {
            string baseDir = System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
            string thisFilename = baseDir + @"\Reports\homeworkReportFrom" + DateTime.Now.ToFileTime().ToString() + ".txt";
            if (!Directory.Exists(baseDir + @"\Reports"))
            {
                Directory.CreateDirectory(baseDir + @"\Reports");
            }
            using (StreamWriter writer = new StreamWriter(thisFilename))
            {
                writer.Write(resultBuilder.ToString());
            }
            OpenFile(thisFilename);
        }

        private void GenerateDefaultRecension()
        {
            StringBuilder resultBuilder = new StringBuilder();
            StringBuilder tasksResBuilder = new StringBuilder();
            bool hasTasksToWrite = false;
            foreach (TaskBox task in this.Tasks_List.Children)
            {
                if (task.ShowTaskInReport)
                {
                    string taskName = task.TaskName;
                    TaskStatus taskStatus = task.Status;
                    string taskStatusString = "";
                    switch (taskStatus)
                    {
                        case TaskStatus.Finished:
                            taskStatusString = "Задачата е направена.";
                            break;
                        case TaskStatus.NotFinished:
                            taskStatusString = "Задачата не е довършена.";
                            break;
                        default:
                            taskStatusString = "Задачата e празна.";
                            break;
                    }
                    hasTasksToWrite = true;
                    tasksResBuilder.AppendLine(string.Format("{0} {1} {2}", taskName, taskStatusString, task.Comment));
                }
            }
            bool hasExtraComment = String.IsNullOrEmpty(this.AdditionalComment_TextBlock.Text) == false;
            if (hasTasksToWrite == false && hasExtraComment == false)
            {
                ShowMessage("Липсва достатъчно съдържание за генериране на рецензия.");
                return;
            }
            if (hasTasksToWrite)
            {
                resultBuilder.AppendLine(new string('-', 20));
                resultBuilder.AppendLine("КОМЕНТАР ПО ЗАДАЧИТЕ");
                resultBuilder.AppendLine(new string('-', 20));
                resultBuilder.Append(tasksResBuilder.ToString());
            }
            if (hasExtraComment)
            {
                resultBuilder.AppendLine(new string('-', 20));
                resultBuilder.AppendLine("ДОПЪЛНИТЕЛЕН КОМЕНТАР");
                resultBuilder.AppendLine(new string('-', 20));
                resultBuilder.AppendLine(this.AdditionalComment_TextBlock.Text);
            }
            SaveAndOpenRecension(resultBuilder);
        }


        public static void OpenFile(string fileName)
        {
            try
            {
                if (!File.Exists(fileName))
                {
                    throw new IOException();
                }
                System.Diagnostics.Process.Start(fileName);
            }
            catch (IOException boom)
            {
                throw new IOException("Възникна грешка при опита да се отвори файл.", boom.InnerException);
            }
        }

        private void ClearFields_Click(object sender, RoutedEventArgs e)
        {
            bool hasChanges = !this.CheckForDefaultState();
            if (hasChanges)
            {
                bool confirm = AskForConfirmation("Сигурни ли сте че искате да изтриете цялото попълнено съдържание?");
                if (confirm)
                {
                    this.ResetTasksList();
                    this.AdditionalComment_TextBlock.Text = "";
                }
            }
        }

        private void MouseOver(object sender, MouseEventArgs e)
        {
            Control uielement = sender as Control;
            if (uielement != null)
            {
                this.ToolTip_Bar.Content = uielement.ToolTip.ToString();
            }
        }

        private void MouseOut(object sender, MouseEventArgs e)
        {
            this.ToolTip_Bar.Content = "";
        }

        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            bool hasChanges = !CheckForDefaultState();
            if (hasChanges)
            {
                MessageBoxResult confirm = AskForExtendedConfirmation("Искате ли да запишете направената от вас рецензия, преди да напуснете програмата?");
                if (confirm == MessageBoxResult.Yes)
                {
                    this.Cursor = Cursors.Wait;
                    GenerateRecension();
                    this.Cursor = Cursors.Arrow;
                }
                else if (confirm != MessageBoxResult.No)
                {
                    e.Cancel = true;
                }
            }
        }

        private void EditPattern_Click(object sender, RoutedEventArgs e)
        {
            OpenFile("pattern.txt");
        }
    }
}
